package dexter.util;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ByteWrapper {

	public static byte[] wrap(Object ser) throws IOException {
		
		  ByteArrayOutputStream bos = new ByteArrayOutputStream();
		  ObjectOutputStream os = new ObjectOutputStream(bos);
		  os.writeObject(ser);
		  os.close();			
				
		  byte[] bytes = bos.toByteArray();
		  return bytes;

	}
	
	public static Object unwrap(byte[] bytes) throws IOException, ClassNotFoundException {
		
		  ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
		  ObjectInputStream is = new ObjectInputStream(bis);
		  Object ser = is.readObject();
		  is.close();			
		  
		  return ser;
		
	}
	
	public static byte[] getClassBytes(String path, String cn) throws ClassNotFoundException {

		String classname = cn.replace('.', File.separatorChar);
		String filename =  path + classname + ".class";
		
		byte[] bytes = null;
		try {
			
			//System.out.println("filename : "+filename);
		
			File file = new File(filename);
			if (!file.exists()) {
				String[] dirs = {"bin"+File.separator, ".."+File.separator+"bin"+File.separator, ".."+File.separator+".."+File.separator+"bin"+File.separator, 
					 "classes"+File.separator, ".."+File.separator+"classes"+File.separator, ".."+File.separator+".."+File.separator+"classes"+File.separator};
				int i = 0;
		    	while (!file.exists() && i<dirs.length) {
		    		file = new File(dirs[i]+File.separator+filename);	
		    		i++;
		    	}
			}
			if (!file.exists()) return null;
			FileInputStream fis = new FileInputStream(file);
	        
		    //Load class
	        int size = (int) file.length();
	        bytes = new byte[size];

	        // Read in the bytes
	        int offset = 0;
	        int numRead = 0;
	        while (offset < bytes.length && (numRead = fis.read (bytes, offset, bytes.length - offset)) >= 0) {
	          offset += numRead;
	        }
		} catch (Exception e) {
			new ClassNotFoundException("File not found :"+filename,e);
		}
	        return bytes;
	}
	
//	public static Class loadClassFile(String path, String classname, ClassLoader cl) throws IOException, ClassNotFoundException {
//		System.out.println("LOADING CLASS : "+classname+" from "+path);
//		String classfile = classname.replace('.', File.separatorChar);			
//		String filename =  path + classfile + ".class";
//		return loadClassFile(classname, new File(filename),cl);
//	}
	
	public static Class loadClassFile(String classname, File file, ClassLoader cl) throws IOException, ClassNotFoundException {
		
	    //String filename = file.getName();
	    //String classname = filename.substring(0, filename.indexOf('.'));
	    FileInputStream fis = new FileInputStream(file);
		
	    //Load class
        int size = (int) file.length();
        byte[] bytes = new byte[size];

        // Read in the bytes
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length && (numRead = fis.read (bytes, offset, bytes.length - offset)) >= 0) {
          offset += numRead;
        }	    
		
        ByteClassLoader loader = new ByteClassLoader (classname, bytes, cl);
	    //System.out.println("ByteWrapper : loading "+classname);
	    Class c = loader.loadClass (classname);	
	    //System.out.println("ByteWrapper : loaded class from "+file+" ("+bytes.length+" bytes)");
	    return c;
	}
	
	public static File saveClassFile(String path, byte[] classbytes) throws IOException  {
		
		int lastSpr = path.lastIndexOf(File.separatorChar);
		String directory = path.substring(0, lastSpr);
		
		File dir = new File(directory);
		if (!dir.exists()) dir.mkdirs();

		System.out.println("Saving "+classbytes.length+" bytes in "+path);
	    File file = new File(path);
	    FileOutputStream fos = new FileOutputStream(file);
	    
	    fos.write(classbytes);
        
	    return file;
	}
	
}
